01 · ReAct:从零搭一个会用工具的 Agent
零、开始之前
这篇的目标:读完你能自己写出一个真正能干活的 Agent(能查资料、能改文件),并且说得清每一行为什么这么写。
需要的前置知识:会写 Python,调用过一次大模型 API(client.messages.create 这种)。不需要懂任何 Agent 框架。
读完你会明白这几件事:
- 大模型「调用工具」到底是什么意思 —— 它其实什么都没调用
- 一次完整的工具调用,请求和响应里到底传了什么
- 为什么这个循环必须是循环,不能是一次调用
- 什么时候该自己手写,什么时候该上框架
这篇在整个专题里的位置:ReAct 是另外五种范式的地基。后面讲的计划、反思、多智能体,全都是在这个循环外面套东西。所以这一篇必须先啃透。
一、先看一个真实问题
假设你直接问大模型一个问题:
「我这个项目里一共有多少个 Python 文件?」
模型会怎么回答?它只能说「抱歉,我无法访问你的文件系统」。
再问一个:
「LangGraph 现在最新版本是多少?」
模型可能会给你一个版本号,但那是它训练时看到的,大概率已经过期了,而且它不会告诉你这一点。
这两个问题暴露了大模型的两个硬边界:
这座桥就是「工具」。 而 ReAct,就是让模型学会自己走这座桥的方法。
二、最朴素的办法,以及它为什么不够
你可能已经想到一个办法:我自己去查,把结果贴给模型不就行了?
# 第 1 步:你自己在终端跑
$ find . -name "*.py" | wc -l
47
# 第 2 步:把结果贴进 prompt
prompt = "我的项目有 47 个 Python 文件,帮我分析一下规模"
这确实能用。但它有三个问题,而且一个比一个致命:
问题一:你得提前知道要查什么。 如果模型分析到一半发现「还需要看看这些文件多大」,你只能重新跑一次命令、重新组织 prompt。
问题二:多步任务会累死人。 「找出项目里最大的那个 Python 文件,看看它有什么问题」—— 这需要:先列文件 → 再看大小 → 再读内容 → 再分析。四步,你要来回粘贴四次。
问题三:模型没法根据结果调整方向。
如果 find 命令报错了(比如目录不存在),模型看不到错误,你得自己判断、自己改命令。
所以真正的需求是:让模型自己决定要查什么、自己看到结果、自己决定下一步。 你只负责在它开口要的时候,替它跑一下命令。
这就是 ReAct。
三、ReAct 到底是什么
3.1 一个生活里的类比
想象你在电话里指挥一个修水管的师傅,他在现场,你看不见。
- 师傅说:「我先看看总阀在哪」——这是Thought(想)
- 师傅走过去拧开柜门——这是Action(做)
- 师傅说:「柜子里有三个阀门,都锈了」——这是Observation(看到什么)
- 你听完说:「那你先拍张照给我」——下一轮 Thought
ReAct 就是把大模型放在「你」的位置,把你的 Python 代码放在「师傅」的位置。 模型负责想和决定,代码负责跑腿和汇报。
它的名字就是这么来的:Reasoning(推理)+ Acting(行动)。出自 Yao 等人 2022 年的论文,2023 年发表在 ICLR。
论文真正的贡献不是发明了工具调用,而是发现了一件事:让模型把「我为什么要这么做」显式写出来,再决定做什么,准确率会明显高于让它直接做。
3.2 三个词的循环

图 1-1 ReAct 的「思考 → 行动 → 观察」循环
图片来源:Datawhale Hello-Agents 第四章(CC BY-NC-SA 4.0)
用大白话说这张图:
| 阶段 | 谁在干活 | 干了什么 |
|---|---|---|
| Thought | 大模型 | 「我现在缺什么信息」 |
| Action | 大模型决定,你的代码执行 | 「调 bash,参数是 find . -name '*.py'」 |
| Observation | 你的代码 | 把命令的输出原样告诉模型 |
然后回到 Thought,直到模型说「我知道答案了」。